<?php

define('TOURML_NS', 'http://www.imamuseum.org/TourML/1.0');
define('TAP_STOP_VIEW', 'tour_stop_groups');

/**
 * Generate and output the TourML result for a tour
 */
function tap_tourml_export($node)
{
	$tourML = _tap_tourml_tour_export($node);

    header('Content-type: text/xml');
    $tourML->formatOutput = true;
    print $tourML->saveXML();

    exit();   
}

/**
 * Generate the TourML result for a tour
 * @param $node The tour node to process
 * @param $bundle Flag indicating whether to export asset paths relative to a bundle 
 * @return DOMDocument containing the tour metadata
 */
function _tap_tourml_tour_export($node, $bundle = false)
{	
    $tourML = new DOMDocument('1.0', 'UTF-8');

    $tour = $tourML->createElementNS(TOURML_NS, 'Tour');
    $tour->setAttribute('xmlns:xsi', 'http://www.w3.org/2001/XMLSchema-instance');
    $tour->setAttribute('xsi:schemaLocation', TOURML_NS);

    $tour->appendChild($tourML->createElement('Title', $node->title));
    if ($node->body) {
        $tour->appendChild($tourML->createElement('Description', $node->body));
    }

	foreach (_tap_tourml_tour_stops($node) as $stop_node) {
        $element = _tap_tourml_stop_export($tourML, $stop_node, $bundle);
        if (isset($element)) {
        	$tour->appendChild($element);        	
        } else {
        	drupal_set_message("The stop '{$stop_node->title}' could not be exported!");
        }
	}

    $tourML->appendChild($tour);	
	
	return $tourML;
}

/**
 * Return the stop nodes in a tour
 * @param $node The tour node
 */
function _tap_tourml_tour_stops($node)
{
	static $stops = array();
	
	if (!isset($stops[$node->nid]))
	{
		$rs = db_query("select distinct nid from {content_field_tour} where field_tour_nid = %d", $node->nid);
		while ($row = db_fetch_array($rs)) {
			$stops[$node->nid][$row['nid']] = node_load($row['nid']);
		}
	}
	
	return $stops[$node->nid];
}


/**
 * Generate the TourML for a stop
 * @param $doc The TourML document
 * @param $node The stop node to process
 * @param $bundle Flag indicating whether to export asset paths relative to a bundle 
 */
function _tap_tourml_stop_export($doc, $node, $bundle = false)
{
    switch ($node->type) {

    case 'stop_group':
        $stop = $doc->createElement('StopGroup');
        _tap_tourml_add_base_props($doc, $node, $stop);
        
        // Add a header image if provided
        if (!empty($node->field_header_image_portrait) && $node->field_header_image_portrait[0]) {
        	$headerImgPortraitParam = $doc->createElement('Param');
        	$headerImgPortraitParam->setAttribute('key', 'header-image-portrait');
		
	        if ($bundle) {
	    		$headerImgPortraitParam->setAttribute('value', 'images/' . basename($node->field_header_image_portrait[0]['filepath']));
			} else {
				$headerImgPortraitParam->setAttribute('value', file_create_url($node->field_header_image_portrait[0]['filepath'], array('absolute' => true)));
			}

			$stop->appendChild($headerImgPortraitParam);
        }
		if (!empty($node->field_header_image_landscape) && $node->field_header_image_landscape[0]) {
            $headerImgLandscapeParam = $doc->createElement('Param');
            $headerImgLandscapeParam->setAttribute('key', 'header-image-landscape');

            if ($bundle) {
                $headerImgLandscapeParam->setAttribute('value', 'images/' . basename($node->field_header_image_landscape[0]['filepath']));
            } else {
                $headerImgLandscapeParam->setAttribute('value', file_create_url($node->field_header_image_landscape[0]['filepath'], array('absolute' => true)));
            }

            $stop->appendChild($headerImgLandscapeParam);
        }

        $children = array();
        foreach ($node->field_stops as $stop_nid) {
        	$child = node_load($stop_nid['nid']);
        	if (!$child) {
        		drupal_set_message("Skipping invalid node({$stop_nid}) for stop group {$node->title}.", 'warning');
        		continue;
        	}
        	$children[] = $child;
        }
        //usort($children, '_stop_weight_cmp');
        
		foreach ($children as $child) {
		    $stopRef = $doc->createElement('StopRef');
		    $stopRef->setAttribute('id', $child->nid);
		    $stop->appendChild($stopRef);
		}
	
		break;

    case 'image_stop':
        $stop = $doc->createElement('ImageStop');
    	_tap_tourml_add_base_props($doc, $node, $stop);

		if ($bundle) { 	   
    		$srcUrl = 'images/' . basename($node->field_image[0]['filepath']);
		} else {
			$srcUrl = file_create_url($node->field_image[0]['filepath'], array('absolute' => true));					
		}

		$stop->appendChild($doc->createElement('Source', $srcUrl));

        break;

    case 'video_stop':
        $stop = $doc->createElement('VideoStop');
    	_tap_tourml_add_base_props($doc, $node, $stop);

		if ($bundle) {
			$srcUrl = 'videos/' . basename($node->field_video[0]['filepath']);
		} else {
    		$srcUrl = url($node->field_video[0]['filepath'], array('absolute' => true));
		}
    	$stop->appendChild($doc->createElement('Source', $srcUrl));

        break;

    case 'audio_stop':
        $stop = $doc->createElement('AudioStop');
    	_tap_tourml_add_base_props($doc, $node, $stop);

		if ($bundle) {
			$srcUrl = 'videos/' . basename($node->field_video[0]['filepath']);
		} else {
    		$srcUrl = url($node->field_video[0]['filepath'], array('absolute' => true));
		}
    	$stop->appendChild($doc->createElement('Source', $srcUrl));

        break;

	case 'poll_stop':
		$stop = $doc->createElement('PollStop');
		_tap_tourml_add_base_props($doc, $node, $stop);

		$form_type = $doc->createAttribute('form');
		$form_type->appendChild($doc->createTextNode($node->field_form_type[0]['value']));
		$stop->appendChild($form_type);

		$stop->appendChild($doc->createElement('Question', $node->field_question[0]['value']));

		foreach($node->field_answers as $answer) {
			$stop->appendChild($doc->createElement('Answer', $answer['value']));
		}

		break;

	case 'web_stop':
		$stop = $doc->createElement('WebStop');
		_tap_tourml_add_base_props($doc, $node, $stop);
		    	
    	if ($bundle) {
			$srcUrl = 'pages/stop-' . $node->nid . '.html';
		} else {
    		$srcUrl = url('pages/stop-' . $node->nid . '.html', array('absolute' => true));
		}
		
		$stop->appendChild($doc->createElement('Source', $srcUrl));
    	
    	break;
	default:
		// call specialized export for content types provided by other modules
		$stop = array_pop(module_invoke_all('tap_tourml_stop_export', $doc, $node));
    }

    if (!$stop) {
        return null;
    }

    return $stop;
}

function _stop_weight_cmp($a, $b)
{
	if ($a->field_weight[0]['value'] == $b->field_weight[0]['value']) return 0;
	else return ($a->field_weight[0]['value'] > $b->field_weight[0]['value']) ? 1 : -1;
}

function _tap_tourml_add_base_props($doc, $node, &$stop)
{
    $stop->setAttribute('id', _tap_tourml_id($node->nid));
    if ($node->field_code && $node->field_code[0]['value']) {
        $stop->setAttribute('code', $node->field_code[0]['value']);
    }
	if ($node->field_latitude && $node->field_latitude[0]['value']) {
        $stop->setAttribute('latitude', $node->field_latitude[0]['value']);
    }
	if ($node->field_longitude && $node->field_longitude[0]['value']) {
        $stop->setAttribute('longitude', $node->field_longitude[0]['value']);
    }
    
    $stop->appendChild($doc->createElement('Title', htmlspecialchars($node->title, ENT_NOQUOTES, 'UTF-8')));
    if ($node->body) {
        $stop->appendChild($doc->createElement('Description', htmlspecialchars($node->body, ENT_NOQUOTES, 'UTF-8')));
    }
}

function _tap_tourml_replace_href($matches)
{
	$href = split('=', trim($matches[0], '<>')); 	

	$tourml_id = _tap_tourml_id(array_pop(split('/', trim($href[1], '"'))));	
	
	return "<a href='stop://$tourml_id'>";
}


/**
 * Export an OSX Bundle
 * @node The tour node to bundle
 */
function tap_bundle_export($node)
{
	// Check for presense of zip extension
	if (!class_exists('ZipArchive')) {
		drupal_set_message("You must install the php zip extension to export bundles.", 'error');
		return;
	}
	
	$bundle_name = preg_replace('/\s+/', '', $node->title);
			
    $url = file_directory_path()."/$bundle_name-bundle.zip";
	$file = file_check_location($url);

	// Needed because ZipArchive::OVERWRITE has no effect
	file_delete($file);
	
	drupal_set_message("Bundling content in $file");	
		
	$bundle = new ZipArchive();
	if ($bundle->open($file, ZipArchive::OVERWRITE) !== true) {
		drupal_set_message("Could not open $file" , 'error');
		return;
	}

	$bdir = "$bundle_name.bundle";
	$bundle->addEmptyDir($bdir);

	$info = file_get_contents(drupal_get_path('module', 'tap') . '/Info.plist.template');
	
	$domain = join('.', array_reverse(split('\.', variable_get('tap_bundle_domain', 'tap.imamuseum.org'))));

	$info = str_replace(array('BUNDLE_NAME', 'BUNDLE_ID'), 
	                    array($bundle_name, "$domain.$bundle_name"), 
	                    $info);

	$bundle->addFromString("$bdir/Info.plist", $info);

	$bundle->addEmptyDir("$bdir/images");
	$bundle->addEmptyDir("$bdir/videos");
	$bundle->addEmptyDir("$bdir/pages");
	
	$tourml = _tap_tourml_tour_export($node, true);
	$tourml->formatOutput = true;
	
	foreach (_tap_tourml_tour_stops($node) as $stop_node) {
		_tap_bundle_files($stop_node, $bundle, $bdir);
	}

	// Check for translations
	$translations = translation_node_get_translations($node->tnid);
	$default_lang = language_default('language');

	if ($translations)
	{
		$bundle->addEmptyDir("$bdir/$default_lang.lproj");
		$bundle->addFromString("$bdir/$default_lang.lproj/tour.xml" , $tourml->saveXML());	

		drupal_set_message("Bundled locale $default_lang");

		foreach ($translations as $translation)
		{
			if ($translation->language == $default_lang) continue;
			$translated_node = node_load($translation->nid);
			
			$bundle->addEmptyDir("$bdir/{$translation->language}.lproj");
			
			$tourml = _tap_tourml_tour_export($translated_node, true);
			$tourml->formatOutput = true;
			$bundle->addFromString("$bdir/{$translation->language}.lproj/tour.xml" , $tourml->saveXML());
			
			foreach (_tap_tourml_tour_stops($translated_node) as $stop_node) {
				_tap_bundle_files($stop_node, $bundle, $bdir);
			}

			drupal_set_message("Bundled locale {$translation->language}");
		}
	}
	else
	{
		$bundle->addFromString("$bdir/tour.xml" , $tourml->saveXML());	
	}
	
	drupal_set_message("{$bundle->numFiles} files were bundled.");
		
	$bundle->close();
	
	return l('Download the bundle', file_create_path($url));
	
}


function _tap_bundle_files($node, $bundle, $base_dir)
{
	switch($node->type)
	{	
		case 'stop_group':
			if (!empty($node->field_header_image_portrait) && $node->field_header_image_portrait[0]) {
				if ($bundle->locateName("$base_dir/images/" . basename($node->field_header_image_portrait[0]['filepath'])) === false) {
					$bundle->addFile($node->field_header_image_portrait[0]['filepath'],
						                 "$base_dir/images/" . basename($node->field_header_image_portrait[0]['filepath']));
				}
			}
			if (!empty($node->field_header_image_landscape) && $node->field_header_image_landscape[0]) {
				if ($bundle->locateName("$base_dir/images/" . basename($node->field_header_image_landscape[0]['filepath'])) === false) {
					$bundle->addFile($node->field_header_image_landscape[0]['filepath'],
                                         "$base_dir/images/" . basename($node->field_header_image_landscape[0]['filepath']));
				}
			}
			break;

		case 'image_stop':
			if ($bundle->locateName("$base_dir/images/" . basename($node->field_image[0]['filepath'])) === false) {
				$bundle->addFile($node->field_image[0]['filepath'],
					                 "$base_dir/images/" . basename($node->field_image[0]['filepath']));
			}

			$thumb = _tap_generate_thumbnail($node->field_image[0]['filepath']);
			if ($thumb && ($bundle->locateName("$base_dir/images/thumbnails/" . basename($thumb)) === false)) {
				$bundle->addFile($thumb, "$base_dir/images/thumbnails/" . basename($thumb));
			}
			break;

		case 'video_stop':
		case 'audio_stop':
			if ($bundle->locateName("$base_dir/videos/" . basename($node->field_video[0]['filepath'])) === false) {
				$bundle->addFile($node->field_video[0]['filepath'],
	    			                 "$base_dir/videos/" . basename($node->field_video[0]['filepath']));
			}
			break;

		case 'web_stop':
			$bundle->addFromString("$base_dir/pages/stop-{$node->nid}.html",
			_tap_tourml_webstop_content($node, true));
			break;
	}
}



function _tap_tourml_webstop_content($node, $bundle = false) {

	$content = check_markup($node->field_web_content[0]['value'], $node->field_web_content[0]['format'], false);
	
	if ($bundle) {
	
		$content = preg_replace('/http:\/\/tap-dev\/sites\/tap-dev\/files\/imagecache\/thumbnail/', 
		                        '../images/thumbnails', $content);
	}
	
	$content = preg_replace_callback('/<a href="(\/[a-z][a-z])?\/node\/[0-9]+">/', '_tap_tourml_replace_href', $content);	
	
	return $content;
	
}


function _tap_generate_thumbnail($path, $presetname = 'thumbnail') {
	
	if (!$preset = imagecache_preset_by_name($presetname)) {
		drupal_set_message("Preset $presetname not found!", 'warning');	
		return null;
	}	

	$dst = imagecache_create_path($preset['presetname'], $path);
  	if (is_file($dst)) {
		return $dst;
  	}

	$src = $path;
	if (!is_file($src) && !is_file($src = file_create_path($src))) {
		drupal_set_message("File $src does not exist!", 'warning');
		return null;
	}

	if (!getimagesize($src)) {
		drupal_set_message("$src is not an image!", 'warning');
		return null;	
	}

	imagecache_build_derivative($preset['actions'], $src, $dst);
	
	return $dst;
	
}

/**
 * Poll callback for submitting a vote.
 * Return an xml representation of the results.
 */
function tap_tourml_vote($node, $answer) {
	if ($node->type == 'poll_stop') {
		$votes = array(
			'content_type' => 'node',
			'content_id' => $node->nid,
			'value_type' => 'option',
			'value' => 1,
			'tag' => $answer,
		);
		
		$results = votingapi_set_votes($votes,$criteria = array());

   		$resultXML = new DOMDocument('1.0', 'UTF-8');

    	$poll = $resultXML->createElement('Result');

		foreach ($results['node'][$node->nid] as $val) {
			$votes = $resultXML->createElement('vote');
			$votes->setAttribute('option',$val['tag']);
			$votes->setAttribute('value',$val['value']);	
    		$poll->appendChild($votes);
		}

		$resultXML->appendChild($poll);
   		header('Content-type: text/xml');
    	$resultXML->formatOutput = true;
    	print $resultXML->saveXML();
		exit();
	}

	drupal_access_denied();
}

/**
 * Analytics callback for recording an event
 */
function tap_tourml_analytics($stop_id, $action, $device_timestamp, $device_uuid, $device_name)
{
	db_query("insert into {tap_analytics} (stop_id, action, device_uuid, device_name, device_timestamp, server_timestamp) " .
		"values ('%s', '%s', '%s', '%s', %d, %d)", $stop_id, $action, $device_uuid, $device_name, $device_timestamp, time());
	
	print 'Thanks';
	exit();
}
